package com.wmh.baseservice.skd.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wmh.baseservice.common.service.TokenService;
import com.wmh.baseservice.common.utils.returnbody.ReturnBody;
import com.wmh.baseservice.skd.pojo.SkdGoodsCategory;
import com.wmh.baseservice.skd.pojo.SkdGoodsInfo;
import com.wmh.baseservice.skd.pojo.SkdGoodsSpec;
import com.wmh.baseservice.skd.pojo.vo.GoodsRespVO;
import com.wmh.baseservice.skd.pojo.vo.ModifyGoodsReqVO;
import com.wmh.baseservice.skd.service.SkdGoodsCategoryService;
import com.wmh.baseservice.skd.service.SkdGoodsInfoService;
import com.wmh.baseservice.skd.service.SkdGoodsLabelService;
import com.wmh.baseservice.skd.service.SkdGoodsSpecService;
import com.wmh.baseservice.skd.pojo.vo.AddGoodsReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "商品管理相关接口")
@Validated
@RestController
@RequestMapping(value = "goods", produces = "text/plain;charset=utf-8")
@Slf4j
public class GoodsInfoController {
    @Resource
    private TokenService tokenService;
    @Resource
    private SkdGoodsLabelService skdGoodsLabelService;
    @Resource
    private SkdGoodsCategoryService skdGoodsCategoryService;
    @Resource
    private SkdGoodsInfoService skdGoodsInfoService;
    @Resource
    private SkdGoodsSpecService skdGoodsSpecService;

    /**
     * #0012 添加商品标签
     * @param label 添加的商品标签名
     */
    @ApiOperation(value = "添加商品标签")
    @PostMapping("labels")
    public String addGoodsLabel(@NotBlank(message = "未提交商品标签") String label) {
        Long usId;
        try {
            // 根据token获取用户id
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }

        // 查询是否有同名的商品标签
        boolean labelExists = skdGoodsLabelService.selectLabelByNameAndUsId(usId, label);

        // 如果标签不存在，则添加标签
        if (!labelExists) {
            skdGoodsLabelService.addGoodsLabel(usId, label);
            return ReturnBody.success("添加成功!");
        } else {
            return ReturnBody.error("标签已存在!");
        }
    }

    /**
     * #0013 根据用户id查询全部商品标签
     * @return 返回商品标签列表
     */
    @ApiOperation(value = "根据用户id查询全部商品标签")
    @GetMapping("labels")
    public String queryLabelsByUsId() {
        Long usId;
        try {
            // 根据token获取用户id
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }
        List<Map<String, Object>> labelList = skdGoodsLabelService.queryLabelsByUsId(usId);
        return ReturnBody.success(labelList);
    }

    /**
     * #0014 删除商品标签
     * @param label 删除的商品标签名
     */
    @ApiOperation(value = "删除商品标签")
    @DeleteMapping("labels")
    public String deleteLabel(@NotBlank(message = "未提交商品标签") String label) {
        Long usId;
        try {
            // 根据token获取用户id
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }
        skdGoodsLabelService.deleteLabel(usId, label);
        return ReturnBody.success("删除成功!");
    }

    /**
     * #0015 添加商品分类
     * @param category 商品分类
     */
    @ApiOperation(value = "添加商品分类")
    @PostMapping("categories")
    public String addGoodsCategory(@NotBlank(message = "未提交商品分类") String category) {
        Long usId;
        try {
            // 根据token获取用户id
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }
        // 查询是否有同名的商品分类
        boolean categoryExists = skdGoodsCategoryService.selectCategoryByNameAndUsId(usId, category);

        // 如果分类不存在，则添加分类
        if (!categoryExists) {
            skdGoodsCategoryService.addGoodsCategory(usId, category);
            return ReturnBody.success("添加成功!");
        } else {
            return ReturnBody.error("分类已存在");
        }
    }

    /**
     * #0016 删除商品分类
     * @param category 删除的商品分类
     */
    @ApiOperation(value = "删除商品标签")
    @DeleteMapping("categories")
    public String deleteCategory(@NotBlank(message = "未提交商品分类") String category) {
        Long usId;
        try {
            // 根据token获取用户id
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }
        skdGoodsCategoryService.deleteCategory(usId, category);
        return ReturnBody.success("删除成功!");
    }

    /**
     * #0017 修改商品分类
     */
    @ApiOperation("修改商品分类")
    @PutMapping("categories")
    public String modifyCategories(@NotNull(message = "未提交分类id") Long categoryId, @NotBlank(message = "未提交商品分类") String categoryName) {
        SkdGoodsCategory res = skdGoodsCategoryService.getById(categoryId);
        if (Objects.isNull(res)) {
            return ReturnBody.error("分类不存在!");
        }
        SkdGoodsCategory skdGoodsCategory = new SkdGoodsCategory();
        skdGoodsCategory.setId(categoryId).setCategoryName(categoryName);
        skdGoodsCategoryService.saveOrUpdate(skdGoodsCategory);
        return ReturnBody.success("修改成功!");
    }

    /**
     * #0018 查询全部商品标签
     * @return 返回商品标签列表
     */
    @ApiOperation(value = "查询全部商品标签")
    @GetMapping("categories")
    public String queryCategoryByUsId() {
        Long usId;
        try {
            // 根据token获取用户id
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }
        List<Map<String, Object>> categoryList = skdGoodsCategoryService.queryCategoryByUsId(usId);
        return ReturnBody.success(categoryList);
    }


    /**
     * #0019 商品库添加商品
     */
    @ApiOperation(value = "商品库添加商品")
    @PostMapping
    public String addGoods(@Valid AddGoodsReqVO reqVO) {
        return ReturnBody.success(skdGoodsInfoService.addGoods(reqVO));
    }

    /**
     * #0020 删除商品库内商品
     * @param goodsId 删除的商品id
     * @return 返回是否删除成功信息
     */
    @ApiOperation(value = "删除商品库内商品")
    @DeleteMapping
    public String deleteGoodsById(@NotNull(message = "未提交商品id") Long goodsId) {
        SkdGoodsInfo res = skdGoodsInfoService.getById(goodsId);
        if (Objects.isNull(res)) {
            return ReturnBody.error("该商品不存在");
        }
        skdGoodsInfoService.removeById(goodsId);
        return ReturnBody.success("删除成功!");
    }

    /**
     * #0021 修改商品库内商品
     * @param reqVO 修改商品库商品请求体封装
     * @return 返回是否修改成功信息
     */
    @ApiOperation(value = "修改商品库内商品")
    @PutMapping
    public String modifyGoodsInfo(@Valid ModifyGoodsReqVO reqVO) {
        log.info("修改的商品数据: " + reqVO);

        SkdGoodsInfo res = skdGoodsInfoService.getById(reqVO.getId());
        if (Objects.isNull(res)) {
            return ReturnBody.error("商品id有误, 没有对应商品!");
        }
        // 如果商品没有规格,则入参必须有单价
        if (Objects.isNull(reqVO.getPrice()) && StrUtil.isBlank(reqVO.getGoodsSpec())) {
            return ReturnBody.error("未提交商品单价!");
        }
        // 如果商品有规格,则校验参数是否为有效格式
        if (StrUtil.isNotBlank(reqVO.getGoodsSpec()) && !skdGoodsInfoService.isValidGoodsSpec(reqVO.getGoodsSpec())) {
            return ReturnBody.error("商品规格格式有误!");
        }
        SkdGoodsInfo skdGoodsInfo = new SkdGoodsInfo();
        skdGoodsInfo
                .setId(reqVO.getId())
                .setName(reqVO.getName())
                .setDescription(reqVO.getDescription())
                .setImgUrl(reqVO.getImgUrl())
                .setVideoUrl(reqVO.getVideoUrl())
                .setPrice(StrUtil.isBlank(reqVO.getGoodsSpec()) ? reqVO.getPrice() : new BigDecimal(-1))
                .setCrossedPrice(reqVO.getCrossedPrice())
                .setGoodsNo(reqVO.getGoodsNo())
                .setLabels(reqVO.getLabels().stream() // List<Integer> 转换为逗号分隔的字符串
                        .map(String::valueOf)
                        .collect(Collectors.joining(",")))
                .setCategoryId(reqVO.getCategoryId())
                .setHasSpec(StrUtil.isBlank(reqVO.getGoodsSpec()) ? -1 : 1);

        skdGoodsInfoService.saveOrUpdate(skdGoodsInfo);
        if (StrUtil.isNotBlank(reqVO.getGoodsSpec())) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                List<SkdGoodsSpec> newSpecs = mapper.readValue(reqVO.getGoodsSpec(), new TypeReference<List<SkdGoodsSpec>>() {
                });

                // 获取现有的规格
                List<SkdGoodsSpec> existingSpecs = skdGoodsSpecService.getGoodsSpecListByGoodsId(reqVO.getId());

                log.info("商品对应商品规格: " + existingSpecs);

                // 处理规格更新和添加
                newSpecs.forEach(newSpec -> {
                    Optional<SkdGoodsSpec> existingSpec = existingSpecs.stream()
                            .filter(es -> es.getId().equals(newSpec.getId()))
                            .findFirst();
                    if (existingSpec.isPresent()) {
                        // 更新现有规格
                        log.info("更新现有规格");
                        skdGoodsSpecService.saveOrUpdate(newSpec);
                    } else {
                        // 添加新规格
                        log.info("添加新规格");
                        newSpec.setGoodsId(reqVO.getId());
                        skdGoodsSpecService.save(newSpec);
                    }
                });

                // 删除不再需要的规格
                existingSpecs.forEach(existingSpec -> {
                    if (newSpecs.stream().noneMatch(newSpec -> newSpec.getId().equals(existingSpec.getId()))) {
                        log.info("删除不再需要的规格");
                        skdGoodsSpecService.removeById(existingSpec.getId());
                    }
                });

            } catch (JsonProcessingException e) {
                log.error("解析异常: {}", e.getMessage());
                return ReturnBody.error("请检查商品规格参数格式是否正确");
            }
        } else { // 如果商品没有设置规格, 则删除原有对应商品规格
            skdGoodsSpecService.remove(new QueryWrapper<SkdGoodsSpec>().eq("goods_id", reqVO.getId()));
        }

        return ReturnBody.success("修改成功!");
    }

    /**
     * #0022 查询商品库内商品信息。
     * @param categoryId 分类ID，用于筛选特定分类的商品。
     * @param goodsName 商品名称，用于筛选特定名称的商品。
     * @return 返回商品信息列表。
     */
    @ApiOperation("查询商品库内商品")
    @GetMapping
    public String queryGoodsList(Integer categoryId, String goodsName) {
        Long usId;
        try {
            // 根据token获取用户ID
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }

        List<GoodsRespVO> goodsRespVOList = new ArrayList<>();

        QueryWrapper<SkdGoodsInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", usId)
//                .eq("off_shelves", 0)
                .eq(categoryId != null, "category_id", categoryId)
                .like(goodsName != null, "name", goodsName);

        List<SkdGoodsInfo> res = skdGoodsInfoService.list(queryWrapper);

        for (SkdGoodsInfo goods : res) {
            GoodsRespVO goodsRespVO = new GoodsRespVO();
            goodsRespVO.setGoodsId(goods.getId())
                    .setName(goods.getName())
                    .setDescription(goods.getDescription())
                    .setCrossedPrice(goods.getCrossedPrice());
            // 设置商品图片URL和规格相关信息
            setGoodsImageAndSpecs(goods, goodsRespVO);

            goodsRespVOList.add(goodsRespVO);
        }
        return ReturnBody.success(goodsRespVOList);
    }

    /**
     * #0004 修改商品规格
     */
    @ApiOperation("修改商品规格")
    @PutMapping("modify-goods-spec")
    public String modifyGoodsSpec(@NotNull(message = "未提交商品id") Long goodsId, @NotBlank(message = "未提交商品规格") String spec){
        Long usId;
        try {
            // 根据token获取用户ID
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }
        SkdGoodsInfo res = skdGoodsInfoService.getById(goodsId);
        if (Objects.isNull(res)) {
            ReturnBody.error("该商品不存在!");
        }
        return skdGoodsInfoService.modifyGoodsSpec(usId, goodsId, spec);
    }

    /**
     * #0055 查看已下架商品
     * @return 返回已下架商品列表
     */
    @ApiOperation("查看已下架商品")
    @GetMapping("off-shelves-goods")
    public String queryOffShelvesGoods(Integer categoryId, String goodsName) {
        Long usId;
        try {
            // 根据token获取用户ID
            usId = tokenService.getUserIdFromToken();
        } catch (IllegalStateException e) {
            log.error(e.getMessage());
            return ReturnBody.error("token异常!");
        }

        List<GoodsRespVO> goodsRespVOList = new ArrayList<>();

        QueryWrapper<SkdGoodsInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", usId)
                .eq("off_shelves", 1)
                .eq(categoryId != null, "category_id", categoryId)
                .like(goodsName != null, "name", goodsName);

        List<SkdGoodsInfo> list = skdGoodsInfoService.list(queryWrapper);
        list.forEach( goods -> {
            GoodsRespVO goodsRespVO = new GoodsRespVO();
            goodsRespVO.setGoodsId(goods.getId())
                    .setName(goods.getName())
                    .setDescription(goods.getDescription())
                    .setCrossedPrice(goods.getCrossedPrice());
            // 设置商品图片URL和规格相关信息
            setGoodsImageAndSpecs(goods, goodsRespVO);

            goodsRespVOList.add(goodsRespVO);

        });
        return ReturnBody.success(goodsRespVOList);
    }

    /**
     * #0056 下架商品
     * @param goodsId 商品id
     * @return 返回是否下架成功信息
     */
    @ApiOperation("下架商品")
    @PostMapping("down")
    public String downGoods(@NotNull(message = "未提交商品id") Long goodsId) {
        SkdGoodsInfo skdGoodsInfo = skdGoodsInfoService.getById(goodsId);
        if (Objects.isNull(skdGoodsInfo)) {
            return ReturnBody.error("该商品不存在");
        }
        skdGoodsInfo.setOffShelves(1);
        skdGoodsInfoService.saveOrUpdate(skdGoodsInfo);
        return ReturnBody.success("下架成功!");
    }

    /**
     * #0057 上架商品
     * @param goodsId 商品id
     * @return 返回是否上架成功信息
     */
    @ApiOperation("上架商品")
    @PostMapping("up")
    public String upGoods(@NotNull(message = "未提交商品id") Long goodsId) {
        SkdGoodsInfo skdGoodsInfo = skdGoodsInfoService.getById(goodsId);
        if (Objects.isNull(skdGoodsInfo)) {
            return ReturnBody.error("该商品不存在");
        }
        skdGoodsInfo.setOffShelves(0);
        skdGoodsInfoService.saveOrUpdate(skdGoodsInfo);
        return ReturnBody.success("上架成功!");
    }
    /**
     * 设置商品图片URL和规格相关信息。
     * @param goods 商品信息。
     * @param goodsRespVO 商品响应VO。
     */
    private void setGoodsImageAndSpecs(SkdGoodsInfo goods, GoodsRespVO goodsRespVO) {
        // 解析并设置商品图片URL
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            List<String> urls = objectMapper.readValue(goods.getImgUrl(), new TypeReference<List<String>>() {});
            goodsRespVO.setImgUrl(urls.get(0)); // 设置首张商品图片地址
        } catch (IOException e) {
            e.printStackTrace();
            log.info(e.getMessage());
        }

        // 设置价格范围和规格信息
        setPriceAndInventory(goods, goodsRespVO);
    }

    /**
     * 设置商品的价格范围和库存信息。
     * @param goods 商品信息。
     * @param goodsRespVO 商品响应VO。
     */
    private void setPriceAndInventory(SkdGoodsInfo goods, GoodsRespVO goodsRespVO) {
        if (goods.getHasSpec() != -1) {
            List<SkdGoodsSpec> goodsSpecs = skdGoodsSpecService.getPriceRangeByGoodsId(goods.getId());
            setPriceRangeAndSpecs(goodsSpecs, goodsRespVO);
        } else {
            goodsRespVO.setPriceRange(goods.getPrice().toString());
        }
    }

    /**
     * 设置商品的价格范围和规格描述。
     * @param goodsSpecs 商品规格信息。
     * @param goodsRespVO 商品响应VO。
     */
    private void setPriceRangeAndSpecs(List<SkdGoodsSpec> goodsSpecs, GoodsRespVO goodsRespVO) {
        if (!goodsSpecs.isEmpty()) {
            BigDecimal minPrice = goodsSpecs.get(0).getPrice();
            BigDecimal maxPrice = goodsSpecs.get(goodsSpecs.size() - 1).getPrice();
            goodsRespVO.setPriceRange(minPrice + "-" + maxPrice);

            List<String> specs = new ArrayList<>();
            boolean unlimitedInventory = false;

            for (SkdGoodsSpec spec : goodsSpecs) {
                specs.add(spec.getDescription());
                if (spec.getInventory() == -1) {
                    unlimitedInventory = true;
                }
            }

            goodsRespVO.setInventory(unlimitedInventory ? -1 : calculateTotalInventory(goodsSpecs));
            goodsRespVO.setSpec(String.join(", ", specs));
        }
    }

    /**
     * 计算商品的总库存。
     * @param goodsSpecs 商品规格信息。
     * @return 返回总库存数量。
     */
    private int calculateTotalInventory(List<SkdGoodsSpec> goodsSpecs) {
        return goodsSpecs.stream()
                .filter(spec -> spec.getInventory() != -1)
                .mapToInt(SkdGoodsSpec::getInventory)
                .sum();
    }
}
